package xyz.eden.boot.common.web.support.infrastructure.publish.event;

import lombok.Getter;
import org.springframework.context.ApplicationEvent;
import xyz.eden.boot.common.web.support.infrastructure.publish.enums.EventTypeEnum;

import java.util.Objects;

@Getter
public class ModelChangeEvent extends ApplicationEvent {

    /**
     * action type.
     */
    private final EventTypeEnum type;

    /**
     * before data.
     */
    private final Object before;

    /**
     * after data.
     */
    private final Object after;

    /**
     * operator:is user or app.
     */
    private final String operator;

    /**
     * consumed.
     */
    private boolean consumed;

    /**
     * event date.
     */
    private final Long publishTimestamp;

    public ModelChangeEvent(Object source, EventTypeEnum type, Object before) {
        this(source, type, before, source, null);
    }

    public ModelChangeEvent(Object source, EventTypeEnum type, Object before, Object after, String operator) {
        super(source);
        this.type = type;
        Object beforeData = null;
        Object afterData = null;
        switch (type) {
            case CREATE -> {
                afterData = source;
            }
            case DELETE -> {
                beforeData = source;
            }
            default -> {
                beforeData = before;
                afterData = after;
            }
        }
        this.before = beforeData;
        this.after = afterData;
        this.operator = Objects.isNull(operator) ? "unknown" : operator;
        this.consumed = false;
        this.publishTimestamp = System.currentTimeMillis();
    }

    /**
     * before data snapshot.
     *
     * @return snapshot
     */
    public String beforeSnapshot() {
        return Objects.toString(before, "before unknown");
    }

    /**
     * after data snapshot.
     *
     * @return snapshot
     */
    public String afterSnapshot() {
        return Objects.toString(after, "after unknown");
    }

    /**
     * build event context.
     *
     * @return event context
     */
    public String buildContext() {
        return String.format("%s changed(%s)[%s = > %s]", eventName(), type.getTypeName(), beforeSnapshot(), afterSnapshot());
    }

    /**
     * event name.
     *
     * @return name
     */
    public String eventName() {
        return "data";
    }
}
